/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package webcrawler;
import WebCrawlerBD.Pagina_TempBD;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
/**
 *
 * @author cecv
 */
public class HiloCrawler extends Thread{
     
    private static final String SEARCH = "Search";
    private static final String STOP = "Stop";
    private static final String DISALLOW = "Disallow:";
    private static String newline="\n";
    private static String ContentType="text/html";
    private CrawlerProcess vtn_proceso;
    private Pagina_TempBD pagina_tempBD= new Pagina_TempBD();
    private int prioridad;
    private int dormir=60000;
    private String noProcesar="NO PROCESAR";
    public HiloCrawler(String str, CrawlerProcess vtn_proceso) {
        super(str);
        this.vtn_proceso=vtn_proceso;
    }

    boolean AccesoRobot(URL url)
    {
	String strHost = url.getHost();

	// Extrayendo la URL del archivo robots.txt
	String strRobot = "http://" + strHost + "/robots.txt";
	URL urlRobot;
	try {
	    urlRobot = new URL(strRobot);
	} catch (MalformedURLException e) {
	    // Si la pagina no existe es porque puede que no existe el archivo robots.txt
	    //por lo que si esta permitido el acceso
            return true;
	}

	String strComandos;
	try {
	    InputStream urlRobotTxt = urlRobot.openStream();

	    // leyendo el archivo robots.txt
	    byte b[] = new byte[1000];
	    int numRead = urlRobotTxt.read(b);
	    strComandos = new String(b, 0, numRead);
	    while (numRead != -1) {
		numRead = urlRobotTxt.read(b);
		if (numRead != -1) {
		    String strNuevoComando = new String(b, 0, numRead);
		    strComandos += strNuevoComando;
		}
	    }
	    urlRobotTxt.close();
	} catch (IOException e) {
	    // Si el archivo esta en blanco entonces si esta permitido el acceso
	    return true;
	}
        catch (Exception e)
        {
            return true;

        }

	// Se ha leido el archivo y se tiene comando permitidos y no permitidos
	// Buscamos los comando no permitidos "Disallow:"
	String strURL = url.getFile();
	int index = 0;
	while ((index = strComandos.indexOf(DISALLOW, index)) != -1) {
	    index += DISALLOW.length();
	    String strSubcadena = strComandos.substring(index);
	    StringTokenizer st = new StringTokenizer(strSubcadena);

	    if (!st.hasMoreTokens())
		break;

	    String strPaginaNoPermitida = st.nextToken();

	    //Si la pagina esta como no permitido entonces no hay acceso.
	    if (strURL.indexOf(strPaginaNoPermitida) == 0)
		return false;
	}

	return true;
    }
    private void Imprimir(String resultado){

        this.vtn_proceso.Imprimir(resultado);
    }

    private String URLProcesar()
    {
        int contador=0;
        try
        {
            ArrayList<String> url;
            url=this.pagina_tempBD.UrlSearch();
            this.prioridad=Integer.valueOf(url.get(1));
            this.vtn_proceso.txt_url.setText(url.get(0));
            //Verificando que no exista paginas iguales registradas
            contador=this.pagina_tempBD.PaginaIgualReg(url.get(0));
            if (contador==0)
            {
                return url.get(0);
            }
            else
            {
                //Verificamos que este disponible para actualizar

                //Si no esta disponible para actualizar entonces no se procesa
                String cad=url.get(0).substring(url.get(0).length() - 1, url.get(0).length());
                String urlCad=url.get(0);
                if (cad.compareTo("/")==0)
                {
                    urlCad=url.get(0).substring(0, url.get(0).length()-1);
                }
                this.pagina_tempBD.BorrarPagBusqueda(urlCad);
                this.pagina_tempBD.BorrarPagBusqueda(urlCad+"/");
                return noProcesar;
            }
            
        }
        catch (Exception e)
        {
            this.vtn_proceso.txt_url.setText("No existe Páginas para Buscar");
            Imprimir("No existe Páginas para Buscar");            
            return null;
        
        }


    }

    private String procesarContenido(String contenido) {
        String nuevoContenido="";
        nuevoContenido=contenido.replace('\'', '"');
        return nuevoContenido;
    }

    private void GuardarContenido(URL url, String urlDireccion, String contenido)
    {
      //Proceso que guarda el contenido y la direccion de la URL
      Integer bytes;
      bytes=contenido.getBytes().length;
      String descripcion="Autorización: "+url.getAuthority()
                         +" "+"Protocolo: "+url.getProtocol();
      contenido=procesarContenido(contenido);
      int resultado;
      resultado=pagina_tempBD.RegistrarURL(urlDireccion,descripcion, urlDireccion, contenido, bytes, this.prioridad);
      if (resultado>0)
          Imprimir("URL: Se guardo satisfactoriamente la URL "+urlDireccion+" y su contenido");
      else
          Imprimir("ERROR: Error al guardar la URL "+urlDireccion+" y su contenido");
      //Borrando la pagina de la tabla pagina_busqueda
      resultado=this.pagina_tempBD.BorrarPagBusqueda(urlDireccion);
      if (resultado>0)
          Imprimir("URL: Se borro satisfactoriamente la URL"+urlDireccion+" de pagina de busqueda");
      else
          Imprimir("ERROR: Error al borrar la URL de la tabla pagina de busqueda");


    }

    private void GuardaLink(String url)
    {
        //Verificamos que esta url no este ya procesado
        int contador=this.pagina_tempBD.PaginaIgual(url);
        int resultado;
        if (contador==0)
        {
            //Verificamos si supero el maximo permitido
            
            //Guardamos el link y damos prioridad
            resultado=this.pagina_tempBD.RegistrarLink(url, prioridad+1);
            if (resultado>=0)
                Imprimir("LINK: Se va a guardar el link: "+url);
            else
                Imprimir("ERROR: Error en guardar el link: "+url);

        }
        


    }
    public void run()
    {
        String strURL="";
	String strTargetType = this.vtn_proceso.txt_tipo_contenido.getText();



	while (true)
        {
            // Obteniendo la dirección de la base de datos
            strURL = URLProcesar();
            
            
            if (strURL==null)
            {
                Imprimir("El proceso parará "+dormir/1000+" segundos");
                try
                {
                    this.sleep(dormir);
                    continue;

                }
                catch (Exception es)
                {

                }
                Imprimir("Se inicia el proceso de búsqueda");

            }
            if (strURL.compareTo(this.noProcesar)==0)
            {
                Imprimir("URL: La url "+strURL+" Ya se encuentra en la base de datos");
                continue;
            }
            
            if (strURL.length() == 0) {
                Imprimir("ERROR: La dirección de URL esta vacía");
                continue;
            }
	    Imprimir("Buscando:  " + strURL);

	    URL url;

	    try {
		url = new URL(strURL);
	    } catch (MalformedURLException e) {
		Imprimir("ERROR: URL inválido " + strURL);
		continue;
	    }


	    // Solo se busca información en el protocolo http
	    if (url.getProtocol().compareTo("http") != 0)
		continue;

	    // Verificamos que la dirección este permitida
	    if (!AccesoRobot(url))
		continue;

	    try {
                //Manejamos la URL
		// Abriendo la URL
		URLConnection urlConnection = url.openConnection();

		urlConnection.setAllowUserInteraction(false);

		InputStream urlStream = url.openStream();
		String type = urlConnection.guessContentTypeFromStream(urlStream); //Sacamos el tipo de contenido de la página
		if (type == null) //Si no encontramos el ContentType entonces probamos buscarlo con otra funcion
                {
                    type = urlConnection.getContentType();

                    if (type==null)
                    break;
                }
		if (!type.contains(ContentType))
		    break;

		// Leemos el contenido de la URL
		byte b[] = new byte[1000];
		int numRead = urlStream.read(b);
		String content = new String(b, 0, numRead);
		while (numRead != -1) {

		    numRead = urlStream.read(b);
		    if (numRead != -1) {
			String newContent = new String(b, 0, numRead);
			content += newContent;
		    }
		}
		urlStream.close();

                //Guardamos el contenido de la pagina
                GuardarContenido(url,strURL, content);
                //Buscamos los link de la URL 
		String lowerCaseContent = content.toLowerCase();

		int index = 0;
		while ((index = lowerCaseContent.indexOf("<a", index)) != -1)
		{
		    if ((index = lowerCaseContent.indexOf("href", index)) == -1)
			continue;
		    if ((index = lowerCaseContent.indexOf("=", index)) == -1)
			continue;


		    index++;
		    String remaining = content.substring(index);

		    StringTokenizer st
		      = new StringTokenizer(remaining, "\t\n\r\">#");
		    String strLink = st.nextToken();

		    URL urlLink;
		    try {
			urlLink = new URL(url, strLink);
			strLink = urlLink.toString();
		    } catch (MalformedURLException e) {
			Imprimir("ERROR: URL inválida " + strLink);
			continue;
		    }

		    // Link que solo tengan protocolo http
		    if (urlLink.getProtocol().compareTo("http") != 0)
			continue;

		    
		    try {
			// abriendo URL
			URLConnection urlLinkConnection = urlLink.openConnection();
			urlLinkConnection.setAllowUserInteraction(false);
			InputStream linkStream = urlLink.openStream();
			String strType = urlLinkConnection.guessContentTypeFromStream(linkStream);
			linkStream.close();

			// Verificando que el contenido sea txt/html
			if (strType == null)
                           {
                                strType = urlLinkConnection.getContentType();
                                if (strType==null)
                                continue;
                            }
			if (strType.contains(ContentType)) {
			    //Si la URL link es diferente a esta URL lo mandamos a guardar
			    if (strLink.compareTo(strURL)!=0)
                            {
                                //Si el link esta permitido
                                if (this.AccesoRobot(urlLink))
                                {
                                    GuardaLink(strLink); //Guardamos el link
                                }
                                
                            }
                            
			    
			}

			// if the proper type, add it to the results list
			// unless we have already seen it
			
		    } catch (IOException e) {
			Imprimir("ERROR: El link de la URL no se puede abrir " + strLink);
			continue;
		    }
		}
	    } catch (IOException e) {
		Imprimir("ERROR: La URL no se puede abrir " + strURL);
		continue;
	    }

	    
	}

	
    }


}
